﻿
using NLog;
using NLog.Extensions.Logging;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;



namespace MX.Core.Log
{
    /// <summary>
    /// RY日志【文件区分日志】,使用GetLogger来获取日志
    /// </summary>
    public class Logger : ILogger
    {
        static Microsoft.Extensions.Logging.ILoggerFactory loggerFactory;
        static Logger()
        {
            loggerFactory = new Microsoft.Extensions.Logging.LoggerFactory();
            InitNlog();
        }

        private static void InitNlog()
        {

            var config = new NLog.Config.LoggingConfiguration();
            // Targets where to log to: File and Console
            var logfile = new NLog.Targets.FileTarget("logfile")
            {
                FileName = "${basedir}/logs/${logger:shortName=true}/${shortdate}.txt",
                CreateDirs = true,
                Layout = @"${date:format=HH\:mm\:ss} ${level} ${message} ${exception:format=tostring}",
                OpenFileFlushTimeout = 10,
                OpenFileCacheTimeout = 30,
                ConcurrentWrites = true,
                KeepFileOpen = true,
                Encoding = Encoding.UTF8
            };
            var logconsole = new NLog.Targets.ConsoleTarget("logconsole") {
                Layout = @"${date:format=HH\:mm\:ss} ${level} ${message} ${exception:format=tostring}",
            };

            // Rules for mapping loggers to targets            
            //config.AddRule(LogLevel.Info, LogLevel.Fatal, logconsole);
            //config.AddRule(LogLevel.Debug, LogLevel.Fatal, logfile);
            config.AddRuleForAllLevels(logconsole);
            config.AddRuleForAllLevels(logfile);
            // Apply config           
            LogManager.Configuration = config;

            loggerFactory.AddNLog();
        }



        public string LoggerName { get; private set; }
        public NLog.Logger CoreLog { get; set; }
        private Logger(string loggerName)
            : this(LogManager.GetLogger(loggerName))
        {
            LogManager.GetCurrentClassLogger();
            LoggerName = loggerName;
        }

        private Logger(NLog.Logger coreLog)
        {
            CoreLog = coreLog;
        }

        /// <summary>
        /// 记录提示信息日志
        /// </summary>
        /// <param name="message"></param>
        public void Info(string message)
        {
            CoreLog.Info(message);
        }
        /// <summary>
        /// 记录提示信息日志
        /// </summary>
        /// <param name="message"></param>
        /// <param name="data"></param>
        public void Info(string message, params object[] data)
        {
            CoreLog.Info(message, data);
        }
        /// <summary>
        /// 记录提示信息日志
        /// </summary>
        /// <param name="ex">错误异常</param>
        /// <param name="message">日志消息</param>
        public void Info(Exception ex, string message)
        {
            CoreLog.Info(ex, message);
        }
        /// <summary>
        /// 记录提示信息日志
        /// </summary>
        /// <param name="ex">错误异常</param>
        /// <param name="message">日志消息，可以带“{x}”之类的格式符标记，代表附加数据</param>
        /// <param name="data">日志消息里的附加数据</param>
        public void Info(Exception ex, string message, params object[] data)
        {
            CoreLog.Info(ex, message, data);
        }


        /// <summary>
        /// 记录调试日志
        /// </summary>
        /// <param name="message"></param>
        public void Debug(string message)
        {
            CoreLog.Debug(message);
        }
        /// <summary>
        /// 记录调试日志
        /// </summary>
        /// <param name="message"></param>
        /// <param name="data"></param>
        public void Debug(string message, params object[] data)
        {
            CoreLog.Debug(message, data);
        }
        /// <summary>
        /// 记录调试日志
        /// </summary>
        /// <param name="ex">错误异常</param>
        /// <param name="message">日志消息</param>
        public void Debug(Exception ex, string message)
        {
            CoreLog.Debug(ex, message);
        }
        /// <summary>
        /// 记录调试日志
        /// </summary>
        /// <param name="ex">错误异常</param>
        /// <param name="message">日志消息，可以带“{x}”之类的格式符标记，代表附加数据</param>
        /// <param name="data">日志消息里的附加数据</param>
        public void Debug(Exception ex, string message, params object[] data)
        {
            CoreLog.Debug(ex, message, data);
        }

        /// <summary>
        /// 记录错误日志
        /// </summary>
        /// <param name="message"></param>
        public void Error(string message)
        {
            CoreLog.Error(message);
        }
        /// <summary>
        /// 记录错误日志
        /// </summary>
        /// <param name="message">日志消息，可以带“{x}”之类的格式符标记，代表附加数据</param>
        /// <param name="data">日志消息里的附加数据</param>
        public void Error(string message, params object[] data)
        {
            CoreLog.Error(message, data);
        }
        /// <summary>
        /// 记录错误日志
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="message"></param>
        public void Error(Exception ex, string message)
        {
            CoreLog.Error(ex, message);
        }
        /// <summary>
        /// 记录错误日志
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="message"></param>
        /// <param name="data"></param>
        public void Error(Exception ex, string message, params object[] data)
        {
            CoreLog.Error(ex, message, data);
        }


        /// <summary>
        /// 记录警告日志
        /// </summary>
        /// <param name="message">日志消息</param>
        public void Warn(string message)
        {
            CoreLog.Warn(message);
        }
        /// <summary>
        /// 记录警告日志
        /// </summary>
        /// <param name="message">日志消息，可以带“{x}”之类的格式符标记，代表附加数据</param>
        /// <param name="data">日志消息里的附加数据</param>
        public void Warn(string message, params object[] data)
        {
            CoreLog.Warn(message, data);
        }
        /// <summary>
        /// 记录警告日志
        /// </summary>
        /// <param name="ex">错误异常</param>
        /// <param name="message">日志消息</param>
        public void Warn(Exception ex, string message)
        {
            CoreLog.Warn(ex, message);
        }
        /// <summary>
        /// 记录警告日志
        /// </summary>
        /// <param name="ex">错误异常</param>
        /// <param name="message">日志消息，可以带“{x}”之类的格式符标记，代表附加数据</param>
        /// <param name="data">日志消息里的附加数据</param>
        public void Warn(Exception ex, string message, params object[] data)
        {
            CoreLog.Warn(ex, message, data);
        }

        /// <summary>
        /// 记录致命错误日志
        /// </summary>
        /// <param name="message">日志消息</param>
        public void Fatal(string message)
        {
            CoreLog.Fatal(message);
        }
        /// <summary>
        /// 记录致命错误日志
        /// </summary>
        /// <param name="message">日志消息，可以带“{x}”之类的格式符标记，代表附加数据</param>
        /// <param name="data">日志消息里的附加数据</param>
        public void Fatal(string message, params object[] data)
        {
            CoreLog.Fatal(message, data);
        }
        /// <summary>
        /// 记录致命错误日志
        /// </summary>
        /// <param name="ex">错误异常</param>
        /// <param name="message">日志消息</param>
        public void Fatal(Exception ex, string message)
        {
            CoreLog.Fatal(ex, message);
        }
        /// <summary>
        /// 记录致命错误日志
        /// </summary>
        /// <param name="ex">错误异常</param>
        /// <param name="message">日志消息，可以带“{x}”之类的格式符标记，代表附加数据</param>
        /// <param name="data">日志消息里的附加数据</param>
        public void Fatal(Exception ex, string message, params object[] data)
        {
            CoreLog.Fatal(ex, message, data);
        }

        static ConcurrentDictionary<string, ILogger> loggerPool = new ConcurrentDictionary<string, ILogger>();
        /// <summary>
        /// 获取日志名称
        /// </summary>
        /// <param name="logName">日志名称</param>
        /// <returns>返回日志记录对象</returns>
        static public ILogger GetLogger(string logName)
        {
            return loggerPool.GetOrAdd(logName, (string key) =>
                  {
                      return new Logger(key);
                  });
        }


        public ILogger this[string logName]
        {
            get
            {
                return GetLogger(logName);
            }

        }

        public static ILogger Default
        {
            get
            {
                var name = StackTraceUsageUtils.GetClassFullName();
                return Logger.GetLogger(name);
            }
        }

        public static Microsoft.Extensions.Logging.ILoggerFactory Factory
        {
            get
            {
                return loggerFactory;
            }
        }
    }
}
